#include <string.h>
#include "common.h"

static int32_t DeepCopyConstraintNames(const STACK_OF(GENERAL_SUBTREE) * subtrees, int32_t i, CfArray *outName, uint32_t nPerSubtreesSize);

int main(int argc, char *argv[])
{
    X509 *cert;
    // 从文件中加载证书
    FILE *cert_file = fopen("/home/ts/document/zhb/ca/userWithNameCon.pem", "r");
    cert = PEM_read_X509(cert_file, NULL, NULL, NULL);
    fclose(cert_file);
    CfArray out;

    NAME_CONSTRAINTS *nameConstraints = X509_get_ext_d2i(cert, NID_name_constraints, NULL, NULL);

    if (NULL == nameConstraints)
    {
        printf("nameConstraints is NULL, at line %d.\n", __LINE__);
        return -1;
    }

    int32_t nPerSubtreesSize = sk_GENERAL_SUBTREE_num(nameConstraints->permittedSubtrees);
    printf("nPerSubtreesSize=%d, at line %d.\n", nPerSubtreesSize, __LINE__);

    int32_t nExcSubtreesSize = sk_GENERAL_SUBTREE_num(nameConstraints->excludedSubtrees);
    printf("nExcSubtreesSize=%d, at line %d.\n", nExcSubtreesSize, __LINE__);

    int32_t size = (nPerSubtreesSize + nExcSubtreesSize);
    int32_t blobSize = sizeof(CfBlob) * size;
    printf("size=%d, sizeof(CfBlob)=%ld, blobSize=%d, at line %d.\n", size, sizeof(CfBlob), blobSize, __LINE__);
    out.data = (CfBlob *)malloc(blobSize);
    if (out.data == NULL)
    {
        printf("Failed to malloc for subjectAltName array!Line = %d.\n", __LINE__);
        return -2;
    }
    memset(out.data, 0, blobSize);
    out.count = size;

    for (int index = 0; index < size; index++)
    {
        if (index < nPerSubtreesSize)
        {
            DeepCopyConstraintNames(nameConstraints->permittedSubtrees, index, &out, 0);
        }
        else
        {
            DeepCopyConstraintNames(nameConstraints->excludedSubtrees, index - nPerSubtreesSize, &out, nPerSubtreesSize);
        }
    }

    printf("success, at line %d.\n", __LINE__);
    return 0;
}

static int32_t DeepCopyConstraintNames(const STACK_OF(GENERAL_SUBTREE) * subtrees, int32_t i, CfArray *outName, uint32_t nPerSubtreesSize)
{
    GENERAL_SUBTREE *subTree = sk_GENERAL_SUBTREE_value(subtrees, i);
    // GENERAL_NAME *general = subTree->base;
    int32_t generalType = 0;
    ASN1_STRING *ans1Str = GENERAL_NAME_get0_value(subTree->base, &generalType);
    // long minLen = ASN1_INTEGER_get(subTree->minimum);
    // long maxLen = ASN1_INTEGER_get(subTree->maximum);
    // printf("minLen=%ld, maxLen=%ld, at line %d.\n", minLen, maxLen, __LINE__);
    unsigned char *minBytes = NULL;
    unsigned char *maxBytes = NULL;
    long minDataLen = i2d_ASN1_INTEGER(subTree->minimum, &minBytes);
    long maxDataLen = i2d_ASN1_INTEGER(subTree->maximum, &maxBytes);
    printf("minDataLen=%ld, maxDataLen=%ld, at line %d.\n", minDataLen, maxDataLen, __LINE__);

    const char *str = (const char *)ASN1_STRING_get0_data(ans1Str);
    if ((str == NULL) || (strlen(str) > HCF_MAX_STR_LEN))
    {
        printf("Failed to get x509 altNames string in openssl!");
        return -1;
    }
    uint32_t nameLen = strlen(str) + 1;
    outName->data[i + nPerSubtreesSize].data = (uint8_t *)malloc(nameLen + minDataLen + maxDataLen);
    if (outName->data[i].data == NULL)
    {
        printf("Failed to malloc for outName!");
        return -2;
    }
    memset(outName->data[i].data, 0, nameLen);

    memcpy(outName->data[i].data, str, nameLen);

    if (minDataLen > 0)
    {
        memcpy(&outName->data[i + nPerSubtreesSize].data[nameLen], minBytes, minDataLen);
    }
    if (maxDataLen > 0)
    {
        memcpy(&outName->data[i + nPerSubtreesSize].data[nameLen + minDataLen], maxBytes, maxDataLen);
    }

    outName->data[i + nPerSubtreesSize].size = nameLen + minDataLen + maxDataLen;
    return 0;
}
